<!DOCTYPE html>
<html>
  <head>
    <meta content="text/html; charset=UTF-8" http-equiv="content-type">
    <title>ch03-01</title>
    <link href="css/style.css" rel="stylesheet" type="text/css">
    <link rel="stylesheet" href="thumbnailviewer.css" type="text/css">
    <script src="thumbnailviewer.js" type="text/javascript">

/***********************************************
* Image Thumbnail Viewer Script- © Dynamic Drive (www.dynamicdrive.com)
* This notice must stay intact for legal use.
* Visit http://www.dynamicdrive.com/ for full source code
***********************************************/

</script> </head>
  <body>
    <div class="os1">3.1 QAudioInput音频采集 </div>
    <br>
    本节介绍使用 QAudioInput 采集指定格式的 PCM 音频。在进行音频采集之前需要进行两项准备工作：
    第一项是电脑里有哪些音频采集设备，有几块声卡，声卡支持哪些采样频率、采样位数、声道数等等， 对于这项工作，Qt 提供了 QAudioDeviceInfo
    类进行声卡数量、支持采样参数的查询。 知道声卡性能参数之后，在声卡允许的参数范围内，使用哪种采样频率、采样位宽、声道数， 就是设置实际采样的参数，Qt
    提供了 QAudioFormat 类表示音频采样参数。选择了声卡，设置了采样参数之后，才能开始音频采集。 <br>
    <br>
    本节内容安排如下：3.1.1 介绍声音设备信息类 QAudioDeviceInfo， 3.1.2 介绍音频采样格式类 QAudioFormat，
    3.1.3 节介绍实时音频采样类 QAudioInput，并学习音频采集示例，采集指定格式的 PCM 原始音频。<br>
    <br>
    <div class="os2">3.1.1 QAudioDeviceInfo 声卡信息查询 </div>
    <br>
    QAudioDeviceInfo
    类通过静态成员函数枚举系统声卡，不仅枚举采集功能声卡设备，播放功能声卡设备也通过该类进行枚举。枚举系统所有声卡设备的静态成员函数如下：<br>
    <div class="code">QList&lt;QAudioDeviceInfo&gt;
      QAudioDeviceInfo::​availableDevices(QAudio::Mode mode)</div>
    参数了的 mode 是指输入或输出模式，只有两个常量数值：<br>
    <br>
    <table class="tabel">
      <tbody>
        <tr class="d1">
          <td style="width: 320px;" align="center"><b>QAudio::Mode 枚举常量</b></td>
          <td style="width: 100px;" align="center"><b>数值</b></td>
          <td align="center"><b> 描述</b></td>
        </tr>
        <tr>
          <td>QAudio::AudioOutput</td>
          <td> 1 </td>
          <td> 枚举音频输出设备。 </td>
        </tr>
        <tr class="d1">
          <td>QAudio::AudioInput</td>
          <td> 0</td>
          <td> 枚举音频输入设备。 </td>
        </tr>
      </tbody>
    </table>
    <br>
    上面函数返回值是声卡设备信息列表，QList 是模板类，可以当做普通数组使用，相当于得到声卡设备数组。<br>
    如果希望获取系统默认的音频采集（输入）或音频播放（输出）设备，那么还有两个静态成员函数：<br>
    <div class="code">QAudioDeviceInfo QAudioDeviceInfo::​defaultInputDevice()
      //默认的一个音频输入设备<br>
      QAudioDeviceInfo QAudioDeviceInfo::​defaultOutputDevice()//默认的一个音频输出设备</div>
    <br>
    具体的声卡性能信息保存在 QAudioDeviceInfo 对象里面，可以通过该类的函数进行查询。下面我们按功能划分列举该类的成员函数：<br>
    （1）查询设备名<br>
    <div class="code">QString deviceName() const</div>
    这个函数返回声卡设备名称字符串，比如输入设备 "Realtek HD Audio Input" ，输出设备 "Realtek HD Audio
    output" 。<br>
    （2）支持的采样参数查询<br>
    查询支持的采样频率：<br>
    <div class="code">QList&lt;int&gt; supportedSampleRates() const</div>
    采样频率单位是赫兹 Hz，该函数返回一个支持列表，比如 8000, 11025, 22050, 44100, 48000, 96000
    。输入和输出设备支持的采样频率可能相同，也可能不同，要注意区别判断。<br>
    查询支持的采样位宽，使用下面函数：<br>
    <div class="code">QList&lt;int&gt; supportedSampleSizes() const</div>
    采样位宽的单位是 1 bit，一般支持的位宽是 8 和 16 bit，少数高级声卡支持 24 bit 或 32 bit 采样位宽。<br>
    与采样位宽绑定的两个参数是采样点数据类型和字节序：<br>
    <div class="code">QList&lt;QAudioFormat::SampleType&gt;
      supportedSampleTypes() const //采样点数据类型，整数、浮点数等<br>
      QList&lt;QAudioFormat::Endian&gt;&nbsp;&nbsp;&nbsp; supportedByteOrders()
      const&nbsp;&nbsp; //采样点数据的字节序</div>
    采样点的数据类型如下表所示：<br>
    <br>
    <table class="tabel">
      <tbody>
        <tr class="d1">
          <td style="width: 320px;" align="center"><b>QAudioFormat::​ SampleType
              枚举常量</b></td>
          <td style="width: 100px;" align="center"><b>数值</b></td>
          <td align="center"><b> 描述</b></td>
        </tr>
        <tr>
          <td>QAudioFormat::Unknown</td>
          <td> 0 </td>
          <td> 没有设置采样点数据类型，未知格式。 </td>
        </tr>
        <tr class="d1">
          <td>QAudioFormat::SignedInt</td>
          <td> 1</td>
          <td> 有符号整数，从最小负数到最大正数。 </td>
        </tr>
        <tr>
          <td>QAudioFormat::UnSignedInt</td>
          <td> 2 </td>
          <td> 无符号整数，从 0 到最大无符号正数。 </td>
        </tr>
        <tr class="d1">
          <td>QAudioFormat::Float</td>
          <td> 3 </td>
          <td> 浮点数采样，-1.0 到 +1.0。 </td>
        </tr>
      </tbody>
    </table>
    <br>
    声卡支持的采样点的数据类型一般都支持无符号整数、有符号整数，少数高端声卡支持浮点数采样。实际使用时一般是 8 bit 配合无符号整数，16 bit
    采用有符号整数，更高位数可能使用有符号整数或者浮点数采样。<br>
    采样点数据的字节序有两种：<br>
    <br>
    <table class="tabel">
      <tbody>
        <tr class="d1">
          <td style="width: 280px;" align="center"><b>QAudioFormat::​ Endian
              枚举常量</b></td>
          <td style="width: 120px;" align="center"><b>数值</b></td>
          <td align="center"><b> 描述</b></td>
        </tr>
        <tr>
          <td>QAudioFormat::BigEndian</td>
          <td> QSysInfo::BigEndian </td>
          <td> 大端字节序，高位字节在前，低位字节在后。 </td>
        </tr>
        <tr class="d1">
          <td>QAudioFormat::LittleEndian</td>
          <td> QSysInfo::LittleEndian</td>
          <td> 小端字节序，低位字节在前，高位字节在后。 </td>
        </tr>
      </tbody>
    </table>
    <br>
    绝大部分主机都是采用小端字节序，一般不需要设置字节序，用系统默认的即可。<br>
    查询声卡支持的通道数使用下面函数：<br>
    <div class="code">QList&lt;int&gt; supportedChannelCounts() const</div>
    通道数一般都支持单声道和双声道立体声，即数值 1 和数值 2 。声卡采集时一般只用单声道或双声道，播放时可能支持更多的声道。<br>
    查询声卡支持的编码格式，使用下面函数：<br>
    <div class="code">QStringList supportedCodecs() const</div>
    声卡直接支持的编码通常只有 "audio/pcm" ，就是原始的音频采样数据流。<br>
    <br>
    上面函数是针对各个参数分别进行查询，如果设置好了一个完整的 QAudioFormat 格式对象，可以一口气查询该对象里所有的参数是否都支持： <br>
    <div class="code">bool isFormatSupported(const QAudioFormat &amp; settings)
      const</div>
    QAudioFormat 对象涵盖的参数也就是上面六项：采样频率、采样位宽、采样点数据类型、字节序、通道数、编码格式。<br>
    <br>
    （3）获取最优格式和近似格式<br>
    如果希望获取声卡最优支持的格式，那么使用下面函数：<br>
    <div class="code">QAudioFormat preferredFormat() const</div>
    这个函数获取最优支持格式的 QAudioFormat 对象，涵盖所有采样参数。<br>
    如果用户或程序员设置了一个希望用的格式，但是这种格式声卡不一定完全支持，那么可以根据这个已设置的格式，通知声卡给出一个最近似的支持的格式：<br>
    <div class="code">QAudioFormat nearestFormat(const QAudioFormat &amp;
      settings) const</div>
    通常用 isFormatSupported() 函数判断指定的格式对象是否受声卡支持，如果不支持就调用 nearestFormat() 获取一个最近似的
    格式进行后续操作。<br>
    <br>
    （4）其他功能函数<br>
    如果判断声卡设备信息对象是否为空，可以用如下函数：<br>
    <div class="code">bool&nbsp; isNull() const</div>
    一般很少遇到声卡设备为空的情况，如果声卡设备为空，那么无法进行输入或输出操作。<br>
    判断两个声卡是否不一样，通过下面函数：<br>
    <div class="code">bool operator!=(const QAudioDeviceInfo &amp; other) const</div>
    判断两个声卡是否一样，使用下面函数：<br>
    <div class="code">bool operator==(const QAudioDeviceInfo &amp; other) const</div>
    如果要将一个声卡设备对象赋值给另一个，使用下面赋值函数：<br>
    <div class="code">QAudioDeviceInfo &amp; operator=(const QAudioDeviceInfo
      &amp; other)</div>
    <br>
    QAudioDeviceInfo 声卡设备信息类的主要内容就是上面那些，我们示范一小段代码，可以枚举所有的声卡采集设备及其支持的参数：<br>
    <div class="code">&nbsp;&nbsp;&nbsp; QList&lt;QAudioDeviceInfo&gt; list =
      QAudioDeviceInfo::availableDevices( QAudio::AudioInput );<br>
      &nbsp;&nbsp;&nbsp; for(int i=0; i&lt;list.count(); i++)<br>
      &nbsp;&nbsp;&nbsp; {<br>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
      qDebug()&lt;&lt;list[i].deviceName(); //设备名<br>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
      qDebug()&lt;&lt;list[i].supportedSampleRates();//采样频率<br>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
      qDebug()&lt;&lt;list[i].supportedSampleSizes();//采样位宽<br>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
      qDebug()&lt;&lt;list[i].supportedSampleTypes();//采样点数据类型<br>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
      qDebug()&lt;&lt;list[i].supportedByteOrders(); //采样点字节序<br>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
      qDebug()&lt;&lt;list[i].supportedChannelCounts();//支持的通道数<br>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
      qDebug()&lt;&lt;list[i].supportedCodecs();&nbsp;&nbsp;&nbsp; //声卡直接支持的编码格式<br>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; qDebug()&lt;&lt;endl;<br>
      &nbsp;&nbsp;&nbsp; }</div>
    qDebug() 是 Qt 里打印调试输出的流对象，在作者主机的输出如下（只有一个采集声卡）：<br>
    <span style=" font-family:'Courier'; font-size:10pt; color:#aa00aa;">"Realtek
      HD Audio Input"</span>
    <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" font-family:'Courier'; font-size:10pt; color:#aa00aa;">(8000, 11025, 22050, 44100, 48000, 96000)</span></p>
    <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" font-family:'Courier'; font-size:10pt; color:#aa00aa;">(8,16)</span></p>
    <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" font-family:'Courier'; font-size:10pt; color:#aa00aa;">(SignedInt, UnSignedInt)</span></p>
    <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" font-family:'Courier'; font-size:10pt; color:#aa00aa;">(LittleEndian)</span></p>
    <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" font-family:'Courier'; font-size:10pt; color:#aa00aa;">(1, 2)</span></p>
    <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" font-family:'Courier'; font-size:10pt; color:#aa00aa;">("audio/pcm")</span></p>
    <br>
    <div class="os2">3.1.2 QAudioFormat 音频采样格式 </div>
    <br>
    QAudioFormat
    类专门表示音频采样格式，包括六方面，即采样频率、采样位宽、采样点数据类型、字节序、通道数、编码格式。我们按照该类函数功能，分别列举如下：<br>
    （1）构造函数和析构函数<br>
    <div class="code">QAudioFormat() //默认构造函数<br>
      QAudioFormat(const QAudioFormat &amp; other)&nbsp; //复制构造函数<br>
      ~QAudioFormat()//析构函数</div>
    默认构造函数设置的数值如下：<br>
    &nbsp;&nbsp;&nbsp; 采样频率：-1；<br>
    &nbsp;&nbsp;&nbsp; 采样通道数：-1；<br>
    &nbsp;&nbsp;&nbsp; 采样位宽：-1；<br>
    &nbsp;&nbsp;&nbsp; 字节序：QSysInfo::ByteOrder，即系统默认的字节序；<br>
    &nbsp;&nbsp;&nbsp; 采样点数据类型：QAudioFormat::Unknown ，未知类型<br>
    &nbsp;&nbsp;&nbsp; 编码格式："" ，空字符串。<br>
    我们在设置采样格式对象的时候，六项中字节序、编码格式是固定的，都采用系统默认的字节序，编码设置为 "audio/pcm"
    ，设置其他的东西也没有用，声卡总是采集 PCM 原始数据流。<br>
    剩下四项都是<b>可以挑选设置的，即采样频率、通道数、采样位宽、采样点数据类型。</b><br>
    <br>
    （2）采样格式设置和获取<br>
    我们用一个表格来展示六项采样参数的设置和获取函数：<br>
    <br>
    <table class="tabel">
      <tbody>
        <tr class="d1">
          <td style="width: 280px;" align="center"><b>设置函数</b></td>
          <td style="width: 120px;" align="center"><b>获取函数</b></td>
          <td align="center"><b> 描述</b></td>
        </tr>
        <tr>
          <td>setSampleRate(int samplerate)</td>
          <td> int sampleRate()&nbsp; </td>
          <td> 采样频率，建议用的数值为 8000, 44100, 48000。 </td>
        </tr>
        <tr class="d1">
          <td>setChannelCount(int channels)</td>
          <td style="height: 17px;"> int channelCount() </td>
          <td> 通道数，一般用 1 或 2。 </td>
        </tr>
        <tr>
          <td>setSampleSize(int sampleSize)</td>
          <td> int sampleSize() </td>
          <td> 采样位宽，一般用 8 或 16 bit。 </td>
        </tr>
        <tr class="d1">
          <td>setSampleType(QAudioFormat::SampleType sampleType)</td>
          <td> QAudioFormat::SampleType&nbsp;&nbsp; &nbsp;sampleType()</td>
          <td> 采样点数据类型，一般 8 bit 位宽使用无符号整数，16 bit 位宽使用有符号整数。 </td>
        </tr>
        <tr>
          <td>setByteOrder(QAudioFormat::Endian byteOrder)</td>
          <td> QAudioFormat::Endian&nbsp;&nbsp; &nbsp;byteOrder() </td>
          <td> 字节序，一般不用设置，使用系统默认的数值。 </td>
        </tr>
        <tr class="d1">
          <td>setCodec(const QString &amp; codec)</td>
          <td> QString codec()</td>
          <td> 编码格式，固定设为"audio/pcm"，因为声卡总是采集 PCM 。 </td>
        </tr>
      </tbody>
    </table>
    <br>
    （3）采样时间片和数据长度换算<br>
    采样频率、通道数、采样位宽会直接影响每秒的原始数据量，QAudioFormat 提供了几个快捷函数，对时间片、帧计数和采样数据长度进行相互换算。<br>
    首先是采样点数转为字节数的函数，比如查询一个采样点（帧，Frame）的字节数：<br>
    <div class="code">int bytesPerFrame() const&nbsp; //一个采样点字节数指 (通道数*采样位宽 /
      8)， 这里的 8 是指 8 bit每字节 </div>
    音频采样的一个采样点字节数是指 （通道数*采样位宽 / 8） ，即包含所有通道的单次采样数据，每秒钟固定有采样频率个数的采样点。如果
    QAudioFormat 对象格式不合法，该函数返回 0 。 <br>
    <br>
    查询多个采样点的字节数，使用下面函数：<br>
    <div class="code">qint32 bytesForFrames(qint32 frameCount) const</div>
    该函数同样以所有通道的单次采样数据作为 1 帧，其返回值满足公式：<br>
    bytes = （通道数*采样位宽 / 8）* frameCount <br>
    如果 QAudioFormat 对象格式不合法，该函数返回 0 。 <br>
    <br>
    如果需要根据微秒数查询时间片里的数据字节数，那么使用如下函数：<br>
    <div class="code">qint32 bytesForDuration(qint64 duration) const</div>
    参数里的 duration 是微秒计数，根据微秒数计算该时间片数据长度：<br>
    bytes = （采样频率 * 通道数 * 采样位宽 / 8）* duration / 1000000<br>
    如果是按照 11025 这种 CD 倍率采样，那么除不尽的小数部分会被舍弃掉，取整后返回。<br>
    如果 QAudioFormat 对象格式不合法，该函数返回 0 。 <br>
    <br>
    反过来，根据字节数计算对应时间片长度，使用下面函数：<br>
    <div class="code">qint64 durationForBytes(qint32 bytes) const</div>
    返回值是微秒计数，计算公式就是上一个公式逆运算：<br>
    duration = (bytes*1000000) / （采样频率 * 通道数 * 采样位宽 / 8）<br>
    遇到除不尽的情况，返回值会取整数。<br>
    <br>
    根据帧计数求时间片的函数如下：<br>
    <div class="code">qint64 durationForFrames(qint32 frameCount) const</div>
    参数里是帧计数，每秒固定有采样频率个数的帧，该函数根据帧计数返回微秒数，计算公式如下：<br>
    duration = frameCount * 1000000 / 采样频率<br>
    <br>
    根据字节数求帧计数的函数如下：<br>
    <div class="code">qint32&nbsp; framesForBytes(qint32 byteCount) const</div>
    该函数计算公式比较简单：<br>
    frames = byteCount / bytesPerFrame()<br>
    <br>
    根据时间片微秒计数求对应帧数的函数如下：<br>
    <div class="code">qint32 framesForDuration(qint64 duration) const</div>
    该函数计算公式如下：<br>
    frames = 采样频率 * duration / 1000000<br>
    上述换算函数遇到除不尽的时候都会取整，如果 QAudioFormat 对象格式不合法，换算函数返回 0，实际使用时要注意判断返回值是否为 0。<br>
    <br>
    （4）其他函数<br>
    判断当前 QAudioFormat 对象格式是否合法的函数为：<br>
    <div class="code">bool isValid() const</div>
    在进行时间片、帧计数、字节数换算之前，要注意判断 QAudioFormat 对象格式是否合法。<br>
    <br>
    判断两个格式对象是否不一样的函数为：<br>
    <div class="code">bool operator!=(const QAudioFormat &amp; other) const</div>
    判断两个格式对象是否一样的函数为：<br>
    <div class="code">bool operator==(const QAudioFormat &amp; other) const</div>
    只有当 QAudioFormat
    所有参数设置都一样时，二者才会相等，即采样频率、采样位宽、采样点数据类型、字节序、通道数、编码格式这六项内容必须完全一样。<br>
    将一个对象赋值给另一个对象，使用下面函数：<br>
    <div class="code">QAudioFormat &amp; operator=(const QAudioFormat &amp;
      other)</div>
    <br>
    无论是音频的输入、输出，都会使用 QAudioFormat 表示采样格式，QAudioBuffer 音频缓冲区类也使用 QAudioFormat
    表示缓冲区里的音频数据格式。对于双声道的音频采样，数据缓冲区一般都是交叉存储的，即 左声道-&gt;右声道-&gt;左声道-&gt;右声道 …… 。 <br>
    <br>
    <div class="os2">3.1.3 QAudioInput 音频采集 </div>
    <br>
    介绍完准备工作，我们开始介绍音频输入类 QAudioInput ，该类根据设置的音频设备和采样格式采集音频数据，并可以自动写入到原始 PCM
    文件、网络套接字，或者手动读取时间片的音频数据。下面我们对 QAudioInput 功能函数分类介绍：<br>
    （1）构造函数和析构函数<br>
    <div class="code">QAudioInput(const QAudioFormat &amp; format =
      QAudioFormat(), QObject * parent = 0)<br>
      QAudioInput(const QAudioDeviceInfo &amp; audioDevice, const QAudioFormat
      &amp; format = QAudioFormat(), QObject * parent = 0)<br>
      ~QAudioInput() //析构函数</div>
    第一个构造函数根据指定采样格式 format 新建音频输入对象，parent
    是父对象，可能是窗口或线程。由于没有指定声卡设备，第一个构造函数自动获取系统的默认输入设备，即利用
    QAudioDeviceInfo::​defaultInputDevice() 设备采集音频。<br>
    第二个构造函数指定了采集设备 audioDevice 和 采样格式 format 进行音频采集。parent
    父对象与采集操作一般没什么关系，无论是窗口主线程还是独立子线程都可以进行音频采集。<br>
    第三个析构函数释放资源，销毁 QAudioInput 音频输入对象。<br>
    <br>
    （2）预先设置函数<br>
    之所以称为预先设置函数，是指在音频采集之前都必须设置好，等到采集开始再设置就没用了。一旦采集开始，这些函数调用都会被忽略。<br>
    比如设置采集的音量：<br>
    <div class="code">void setVolume(qreal volume) //设置音量，1.0 代表100%<br>
      qreal volume() const&nbsp; //获取音量值</div>
    音量值为浮点数，1.0 代表 100% 音量。如果声卡设备不支持音量设置，那么音量就总是 1.0 。<br>
    <br>
    设置缓冲区大小的函数如下：<br>
    <div class="code">void setBufferSize(int value) //设置缓冲区大小<br>
      int bufferSize() const&nbsp;&nbsp;&nbsp; //获取缓冲区大小</div>
    注意这个缓冲区大小只是一个建议值， QAudioInput 对象不一定采用，实际用的缓冲区很可能预先设置的数值不一样。因为音频采集与操作系统、声卡硬件都
    有关系，实际运行时不容易精确控制缓冲区的大小，不是说设置多少就能设置多少。<br>
    音频采集时，由于声卡采集的数据源源不断提供给程序，一片缓冲区是不够用的，一般至少有两片缓冲区交替接收实时采集的音频数据，有时候会用到 5
    片缓冲区接收实时数据，这些缓冲区都是 QAudioInput 对象在内部管理。多片缓冲区的总大小是 bufferSize()
    数值。而单片缓冲区的大小不能设置，可以用下面函数查询：<br>
    <div class="code">int periodSize() const&nbsp; //建议的数据读取长度，一般是一小片缓冲区的字节数</div>
    <br>
    QAudioInput 还可以设置定时触发信号，用于实时读取缓冲区或者检查采集状态：<br>
    <div class="code">void setNotifyInterval(int ms) //设置通知提醒的时间间隔，毫米数<br>
      int notifyInterval() const //获取通知时间间隔</div>
    通知的时间间隔是毫米数，在采集运行时，每隔参数 ms 毫米数都是发一个通知信号 notify() ，这个通知信号稍后讲解。<br>
    <br>
    上述三个设置函数都要在采集开始之前设置，采集过程中可以查询这些参数，但是不能修改音量、缓冲区大小和通知时间间隔。<br>
    <br>
    （3）开始、暂停、恢复、结束采样的函数<br>
    QAudioInput 在构造函数里指定了设备、采样格式之后，就不能再修改设备和采样格式。音量、缓冲区大小、通知时间间隔可以设置，也可以不设置。其实只要
    有设备和采样格式就可以开始采集。<br>
    开始采集的函数有两个：<br>
    <div class="code">void start(QIODevice * device) //用参数 device 保存实时音频数据，开始采集<br>
      QIODevice *&nbsp; start() //开始采集，返回默认的缓冲区设备指针</div>
    QIODevice 是 Qt 的 I/O 文件、网络套接字、内存缓冲设备的通用基类，如果在开始函数里指定了保存音频数据的设备
    device，那么实时录音的 PCM 数据自动写到该设备里面，device 可以是文件、网络套接字等等。如果参数里没有指定设备对象指针，那么
    QAudioInput 提供一个默认缓冲区设备指针作为返回值，程序可以从返回指针指向的设备里面读取实时采样数据。 <br>
    <br>
    录音过程可以被暂停或恢复：<br>
    <div class="code">void suspend() //暂停录音<br>
      void resume()&nbsp; //从暂停状态恢复录音</div>
    如果希望抛弃旧的缓冲区数据，重置录音对象，那么使用下面函数：<br>
    <div class="code">void reset()&nbsp; //抛弃旧的缓冲区数据，重置录音对象</div>
    如果希望停止录音，那么使用如下函数：<br>
    <div class="code">void stop()</div>
    <br>
    （4）状态和信息查询函数<br>
    QAudioInput 进行录音时，可以实时查看录音状态，使用下面函数：<br>
    <div class="code">QAudio::State state() const</div>
    具体的状态常量如下表所示：<br>
    <br>
    <table class="tabel">
      <tbody>
        <tr class="d1">
          <td style="width: 220px;" align="center"><b>QAudio::​State 枚举常量</b></td>
          <td style="width: 80px;" align="center"><b>数值</b></td>
          <td align="center"><b> 描述</b></td>
        </tr>
        <tr>
          <td>QAudio::ActiveState</td>
          <td> 0 </td>
          <td> 活跃状态，设备正在进行录音或播放。 </td>
        </tr>
        <tr class="d1">
          <td>QAudio::SuspendedState</td>
          <td> 1</td>
          <td> 暂停状态，只有suspend()函数才会触发暂停状态 。 </td>
        </tr>
        <tr>
          <td>QAudio::StoppedState</td>
          <td> 2</td>
          <td> 停止状态，设备还没开始工作或者已经停止工作。 </td>
        </tr>
        <tr class="d1">
          <td>QAudio::IdleState</td>
          <td> 3</td>
          <td> 空闲状态，设备正在工作，但缓冲区里没有数据需要处理 。 </td>
        </tr>
      </tbody>
    </table>
    <br>
    QAudio::State 状态常量对输入设备和输出设备是通用的，都是表示工作状态。设备开始录音或播放时，QAudio::ActiveState 和
    QAudio::IdleState 都是正常状态。设备状态改变时，会触发 &nbsp;&nbsp;&nbsp; stateChanged()
    信号，这个信号我们稍后讲解。<br>
    <br>
    音频输入或输出过程如果出错，那么有单独的错误查询函数：<br>
    <div class="code">QAudio::Error error() const</div>
    具体的错误枚举常量如下表所示：<br>
    <br>
    <table class="tabel">
      <tbody>
        <tr class="d1">
          <td style="width: 220px;" align="center"><b>QAudio::​Error 枚举常量</b></td>
          <td style="width: 80px;" align="center"><b>数值</b></td>
          <td align="center"><b> 描述</b></td>
        </tr>
        <tr>
          <td>QAudio::NoError</td>
          <td> 0 </td>
          <td> 没有出错。 </td>
        </tr>
        <tr class="d1">
          <td>QAudio::OpenError</td>
          <td> 1</td>
          <td> 打开音频设备出错。 </td>
        </tr>
        <tr>
          <td>QAudio::IOError</td>
          <td> 2</td>
          <td> 读取或写入音频设备时出错。 </td>
        </tr>
        <tr class="d1">
          <td>QAudio::UnderrunError</td>
          <td> 3</td>
          <td> 数据不足，数据供给速率偏低，没有及时并且足量地提供音频数据给音频设备 。 </td>
        </tr>
        <tr>
          <td>QAudio::FatalError</td>
          <td> 4</td>
          <td> 致命错误，发生了无法修复的错误，音频设备目前无法使用。 </td>
        </tr>
      </tbody>
    </table>
    <br>
    这些错误常量对音频输入设备和输出设备是通用的。除了 NoError 和 UnderrunError，其他三个错误都会导致音频设备无法正常工作。<br>
    <br>
    在 QAudioInput 正常录音时，可以查询已经过去的时间：<br>
    <div class="code">qint64 elapsedUSecs() const</div>
    该函数获取从 start() 函数开始的实时时间，单位是微秒，包括空闲状态和暂停状态的总计时。<br>
    如果忽略空闲状态和暂停状态时间，获取实际处理数据的时间，使用下面函数：<br>
    <div class="code">qint64 processedUSecs() const</div>
    处理数据时间的单位也是微秒。<br>
    <br>
    另外，获取当前采样格式的函数如下：<br>
    <div class="code">QAudioFormat format() const</div>
    这个格式在 QAudioInput 构造函数里面指定，构造之后不能修改。如果要使用新的格式，那么重新定义一个 QAudioInput 对象。<br>
    <br>
    查询实时缓冲区已经采集到数据字节数，使用下面函数：<br>
    <div class="code">int bytesReady() const</div>
    当音频输入对象处于 QAudio::ActiveState 或 QAudio::IdleState 状态时，返回实际采集的字节数，其他状态会返回 0。<br>
    <br>
    （5）信号通知函数<br>
    QAudioInput 自带两个信号，第一个是定时通知信号：<br>
    <div class="code">void notify()</div>
    定时通知按照 setNotifyInterval(int ms) 设置的毫秒时间间隔定时发 notify()
    信号，将该信号关联到槽函数，可以定时从缓冲区读取数据或者检查设备工作状态。 <br>
    <br>
    当设备工作状态发生变化时，触发下面的信号：<br>
    <div class="code">void stateChanged(QAudio::State state)</div>
    QAudio::State 就是 state() 函数获取的工作状态。如果要监控设备工作状态，那么可以定义槽函数关联到该信号。<br>
    <br>
    关于 Qt 的信号和槽函数机制，请读者查看《Qt编程指南》第 4 章：<br>
    <a href="https://qtguide.ustclug.org/" target="new">
      https://qtguide.ustclug.org/</a> <br>
    <br>
    QAudioInput 功能函数就是上面那些，讲了一大堆，读者可以发现没有直接读取缓冲区的函数。那是因为所有的读写操作都封装在 QIODevice
    里面了，包括通知什么时候有数据，都是 QIODevice 的工作。<br>
    如果程序只是单一地保存到文件或发送到网络套接字，并且不进行压缩编码，那么可以不用管实时数据的收发原理，直接调用 start(QIODevice *
    device) 函数，保存文件或者发送到网络套接字的过程是全自动的。<br>
    <br>
    当然，如果程序需要同时保存文件和发送到网络，或者需要压缩编码，那么 start(QIODevice * device)
    仅支持一个设备，不支持两个设备，也不支持压缩编码，那么我们就需要自己实时处理缓冲区的数据了。这种情况下，我们需要使用第二个开始函数：<br>
    QIODevice *&nbsp; start()&nbsp; <br>
    我们保存返回值的缓冲区设备指针，然后通过缓冲区设备的信号判断什么时候有数据：<br>
    <div class="code">void QIODevice::​readyRead()</div>
    当音频采集设备填充了足量数据到 QIODevice 缓冲区设备之后，会自动触发上面的 QIODevice::​readyRead()
    信号，我们定义槽函数关联到该信号，在槽函数里读取实时数据：<br>
    <div class="code">QByteArray QIODevice::​readAll() //读取缓冲区全部数据<br>
      QByteArray QIODevice::​read(qint64 maxSize)&nbsp; //读取最多 maxSize 字节的数据</div>
    上面两个函数的返回值就是字节数组，如果不需要压缩编码，就可以把该字节数组写入到文件和网络套接字。如果需要压缩编码，可以对字节数组的数据压缩编
    码后写入文件 和网络套接字。<br>
    <br>
    我们下面通过一个示例，实时采集音频数据，同时保存到文件并从 UDP 套接字发出去。在示例开始之前，我们先做点准备工作：<br>
    首先在 E: 建立新文件夹 examples ，作为教程示例的主文件夹，然后在 E:\examples 新建 ch03 文件夹，本章的示例都存在
    ch03 文件里面。<br>
    然后下载一个网络调试助手工具，方便调试网络套接字：<br>
    <a href="http://www.cmsoft.cn/download/savage/netassist.rar" target="new">
      http://www.cmsoft.cn/download/savage/netassist.rar </a> <br>
    <br>
    下面我们打开 QtCreator，新建一个 Qt Widgets Application 项目，在新建项目的向导里填写：<br>
    ①项目名称 <b>audioin</b>，创建路径 <b>E:\examples\ch03</b>，点击下一步；<br>
    ②套件选择里面选择全部套件，点击下一步；<br>
    ③类信息界面先选择基类为 <b>QWidget</b>，修改类名为 <b>WidgetAudioIn</b>，点击下一步；<br>
    ④项目管理不修改，点击完成。<br>
    我们先打开 audioin.pro 文件，为项目添加 Qt 多媒体模块和网络模块，在 “QT += ” 一行末尾添加 ：<br>
    <div class="code">#-------------------------------------------------<br>
      #<br>
      # Project created by QtCreator 2018-10-23T08:30:58<br>
      #<br>
      #-------------------------------------------------<br>
      <br>
      QT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; += core gui <b>multimedia network</b><br>
      <br>
      greaterThan(QT_MAJOR_VERSION, 4): QT += widgets<br>
      <br>
      TARGET = audioin<br>
      TEMPLATE = app<br>
      <br>
      <br>
      SOURCES += main.cpp\<br>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; widgetaudioin.cpp<br>
      <br>
      HEADERS&nbsp; += widgetaudioin.h<br>
      <br>
      FORMS&nbsp;&nbsp;&nbsp; += widgetaudioin.ui</div>
    编辑好后保存该文件并关闭。<br>
    我们打开 widgetaudioin.ui 界面文件，按照下图拖入控件：<br>
    <center> <img src="images/ch03/ch03-01-01.png" alt="ui" width="800"> </center>
    第一行控件为：标签“声音输入设备”、组合框 comboBoxDeviceIn，第一行按照水平布局。<br>
    第二行控件为：标签“采样频率”、组合框 comboBoxSampleRate、标签“通道数量”、组合框 comboBoxChannelCount；<br>
    第三行控件为：标签“采样位宽”、组合框 comboBoxSampleSize、标签“采样类型”、组合框 comboBoxSampleType；<br>
    第二行和第三行控件使用一个栅格布局。<br>
    第四行控件为：标签“录音文件路径”、单行编辑器 lineEditFile，第四行使用水平布局。<br>
    第五行控件为：标签“目标IP”、单行编辑器 lineEditIP、标签“目标端口”、单行编辑器 lineEditPort，第五行使用水平布局。<br>
    第六行是两个按钮，“开始”按钮 pushButtonStart，“停止”按钮 pushButtonStop，第六行使用水平布局。<br>
    窗口整体使用垂直布局器，窗口大小 400*240，最后设置五个组合框的属性：<br>
    把组合框的“sizePolicy”属性里的“水平策略”修改为 <b>Expanding</b>，这样组合框就可以自动拉伸。<br>
    <br>
    设置好窗口和属性之后，我们为控件添加槽函数，首先右击第一行的组合框 comboBoxDeviceIn，在右键菜单选择“转到槽...”：<br>
    <center> <img src="images/ch03/ch03-01-02.png" alt="ui" width="800"> </center>
    在弹出对话框选择信号“currentIndexChanged(int)”：<br>
    <center> <img src="images/ch03/ch03-01-03.png" alt="ui"> </center>
    选择该信号之后点击 OK 按钮就自动添加该信号的槽函数了。<br>
    然后我们类似地右击“开始”按钮和“停止”按钮，依次为两个按钮添加 “clicked()”信号的槽函数：<br>
    <center> <img src="images/ch03/ch03-01-04.png" alt="ui"> </center>
    三个槽函数添加完成之后，我们开始编辑代码。首先是头文件 widgetaudioin.h 的内容：<br>
    <div class="code"><span style=" color:#000080;">#ifndef</span><span style=" color:#c0c0c0;">
      </span>WIDGETAUDIOIN_H
      <pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#define</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">WIDGETAUDIOIN_H</span></pre>
      <pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">&lt;QWidget&gt;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">&lt;QAudioDeviceInfo&gt;</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">//声卡设备信息</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">&lt;QAudioFormat&gt;</span><span style=" color:#c0c0c0;">     </span><span
style=" color:#008000;">//音频采样格式</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">&lt;QAudioInput&gt;</span><span style=" color:#c0c0c0;">      </span><span
style=" color:#008000;">//音频输入</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">&lt;QFile&gt;</span><span style=" color:#c0c0c0;">        </span><span
style=" color:#008000;">//保存文件</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">&lt;QUdpSocket&gt;</span><span style=" color:#c0c0c0;">   </span><span
style=" color:#008000;">//发送UDP</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">namespace</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">Ui</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">class</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">WidgetAudioIn</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">class</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">WidgetAudioIn</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">:</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">public</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QWidget</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000080;">Q_OBJECT</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">public</span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">explicit</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">WidgetAudioIn</span><span
style=" color:#000000;">(</span><span style=" color:#800080;">QWidget</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span>parent<span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">0</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">~</span><span style=" font-style:italic; color:#000000;">WidgetAudioIn</span><span
style=" color:#000000;">();</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">private</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#808000;">slots</span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">on_comboBoxDeviceIn_currentIndexChanged</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span>index<span
style=" color:#000000;">);</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">on_pushButtonStart_clicked</span><span
style=" color:#000000;">();</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">on_pushButtonStop_clicked</span><span
style=" color:#000000;">();</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//音频输入设备状态变化监控</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">onDeviceStateChanged</span><span
style=" color:#000000;">(</span><span style=" color:#800080;">QAudio</span><span
style=" color:#000000;">::</span><span style=" color:#800080;">State</span><span
style=" color:#c0c0c0;"> </span>state<span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//缓冲区数据可读</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">onBuffReadyRead</span><span
style=" color:#000000;">();</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">private</span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">Ui</span><span
style=" color:#000000;">::</span><span style=" color:#800080;">WidgetAudioIn</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//保存音频输入对象的指针</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QAudioInput</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span><span style=" color:#800000;">m_pInput</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//保存内存缓冲区设备指针</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QIODevice</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span><span style=" color:#800000;">m_pBuffDevice</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//音频采样格式</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QAudioFormat</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_aFormat</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//音频设备列表</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QList</span><span
style=" color:#000000;">&lt;</span><span style=" color:#800080;">QAudioDeviceInfo</span><span
style=" color:#000000;">&gt;</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_listDevices</span><span
style=" color:#000000;">;</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//保存文件对象</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QFile</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_fileSave</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//发送网络套接字指针</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QUdpSocket</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span><span style=" color:#800000;">m_pSocket</span><span
style=" color:#000000;">;</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//初始化，获取音频设备</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">InitFindDevices</span><span
style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//保存采样点类型的字符串列表</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QList</span><span
style=" color:#000000;">&lt;</span><span style=" color:#800080;">QString</span><span
style=" color:#000000;">&gt;</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_listSampleTypes</span><span
style=" color:#000000;">;</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//开始采样时，禁止修改采样参数，停止后恢复</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">holdParas</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">bool</span><span style=" color:#c0c0c0;"> </span>bHold<span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">};</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#endif</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">//</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">WIDGETAUDIOIN_H</span></pre>
</div>
    该文件首先添加了声卡设备信息、音频采样格式、音频输入、文件、UDP套接字等类的头文件包含。<br>在 WidgetAudioIn 类声明里面，private slots: 是指私有槽函数，头三个槽函数是我们上面用右键菜单添加的；<br>后面两个槽函数是手动编写的，onDeviceStateChanged() 用于实时监控音频输入对象的状态变化；<br>onBuffReadyRead() 用于实时读取缓冲区设备的音频采样数据。<br>private: 一行下面是类的私有变量和函数：<br>ui 指针是新建项目时自动生成，不需要修改；<br>m_pInput 指针用于保存音频输入对象；<br>m_pBuffDevice 保存缓冲区设备，从该缓冲区读取实时的音频采样数据；<br>m_aFormat 是音频采样格式；<br>m_listDevices 用于保存系统里可用的音频采集设备；<br>m_fileSave 就是录音文件对象，将音频采样数据写入到该文件；<br>m_pSocket 是UDP套接字指针，用于发送到网络；<br>函数 InitFindDevices() 用窗口初始化时枚举系统里的声音采集设备；<br>m_listSampleTypes 保存采样点数据类型的字符串，方便显示到组合框里；<br>函数 holdParas(bool bHold) 在“开始”按钮和“停止”按钮里面都调用，开始采集时固定参数，避免采集参数被修改；而停止采集后，重新让采集参数可以编辑。<br>
    <br>接下来分段编辑源文件 widgetaudioin.cpp ，首先是头文件包含和构造函数：<br>
 <div class="code">
<style type="text/css">
p, li { white-space: pre-wrap; }
</style>

<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">"widgetaudioin.h"</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">"ui_widgetaudioin.h"</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">&lt;QDebug&gt;</span><span style=" color:#c0c0c0;">       </span><span
style=" color:#008000;">//调试输出</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">&lt;QMessageBox&gt;</span><span style=" color:#c0c0c0;">  </span><span
style=" color:#008000;">//消息框</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">&lt;QIntValidator&gt;//限定端口号范围</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#800080;">WidgetAudioIn</span><span style=" color:#000000;">::</span><span
style=" color:#000000;">WidgetAudioIn</span><span style=" color:#000000;">(</span><span
style=" color:#800080;">QWidget</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">*</span><span style=" color:#000000;">parent</span><span
style=" color:#000000;">)</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QWidget</span><span
style=" color:#000000;">(</span><span style=" color:#000000;">parent</span><span
style=" color:#000000;">),</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">new</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">Ui</span><span style=" color:#000000;">::</span><span style=" color:#800080;">WidgetAudioIn</span><span
style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setupUi</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">this</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//初始化指针</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_pInput</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">NULL</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_pSocket</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">NULL</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_pBuffDevice</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">NULL</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//采样点类型列表，序号就是类型数值</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">0,1,2,3</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_listSampleTypes</span><span
style=" color:#000000;">&lt;&lt;</span><span style=" color:#008000;">"Unknown"</span><span
style=" color:#000000;">&lt;&lt;</span><span style=" color:#008000;">"SignedInt"</span><span
style=" color:#000000;">&lt;&lt;</span><span style=" color:#008000;">"UnSignedInt"</span><span
style=" color:#000000;">&lt;&lt;</span><span style=" color:#008000;">"Float"</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//初始化，获取音频设备</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">InitFindDevices</span><span
style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre></div>         
          
          我们手动添加了 Qt 打印调试信息、消息框和整数验证器的头文件。<br>构造函数第一句 ui-&gt;setupUi(this) 是自动创建窗口控件，该代码在项目创建时自动添加，我们手动编辑的代码必须放在该行之后。<br>我们手动初始化了 m_pInput、m_pSocket、m_pBuffDevice 三个指针，全部设置为 NULL。<br>然后设置了采样点类型的字符串列表，4 个字符串与 Qt 帮助文档里说明的文本一样。<br>最后调用 InitFindDevices() 函数查找系统里的声音采集设备，显示到窗口的组合框里。<br><br>下面编辑析构函数代码，主要针对成员指针进行清理：<br>
  <div class="code">
<style type="text/css">
p, li { white-space: pre-wrap; }
</style>

<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#800080;">WidgetAudioIn</span><span style=" color:#000000;">::~</span><span
style=" font-style:italic; color:#000000;">WidgetAudioIn</span><span style=" color:#000000;">()</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//这个缓冲设备对象归音频输入对象管理，不要手动删除它</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_pBuffDevice</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">NULL</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//删除音频输入设备和套接字</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">if</span><span
style=" color:#000000;">(</span><span style=" color:#000080;">NULL</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">!=</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_pInput</span><span
style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">delete</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_pInput</span><span
style=" color:#000000;">;</span><span style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_pInput</span><span
style=" color:#c0c0c0;">  </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">NULL</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">if</span><span
style=" color:#000000;">(</span><span style=" color:#000080;">NULL</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">!=</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_pSocket</span><span
style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">delete</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_pSocket</span><span
style=" color:#000000;">;</span><span style=" color:#c0c0c0;">   </span><span style=" color:#800000;">m_pSocket</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">NULL</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">}</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//销毁窗口</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">delete</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">ui</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre></div>
          
          
          缓冲区设备由音频输入对象自动管理，只需要将 m_pBuffDevice 置空，不能手动删除缓冲区设备对象；<br>然后判断音频输入对象指针是否为空，如果不空就删除音频输入对象，将指针置空； <br>套接字指针也是类似地处理，如果非空就删除套接字对象，把指针置空。<br>最后的 delete ui 是新建项目时自动生成的代码。<br><br>下面我们编辑初始化时查找音频设备，并显示到组合框的函数：<br>
  <div class="code">
<style type="text/css">
p, li { white-space: pre-wrap; }
</style>

<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#008000;">//初始化，获取音频设备</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">void</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">WidgetAudioIn</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">InitFindDevices</span><span
style=" color:#000000;">()</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//获取设备列表</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_listDevices</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">QAudioDeviceInfo</span><span style=" color:#000000;">::</span><span
style=" color:#000000;">availableDevices</span><span style=" color:#000000;">(</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QAudio</span><span
style=" color:#000000;">::</span><span style=" color:#800080;">AudioInput</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//添加到组合框</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">for</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">i</span><span style=" color:#000000;">=</span><span style=" color:#000080;">0</span><span
style=" color:#000000;">;</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">i</span><span
style=" color:#000000;">&lt;</span><span style=" color:#800000;">m_listDevices</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">count</span><span
style=" color:#000000;">();</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">i</span><span
style=" color:#000000;">++)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxDeviceIn</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">addItem</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_listDevices</span><span
style=" color:#000000;">[</span><span style=" color:#000000;">i</span><span style=" color:#000000;">].</span><span
style=" color:#000000;">deviceName</span><span style=" color:#000000;">()</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//设置默认文件名，要用右斜杠</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">lineEditFile</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setText</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">"E:/audio_8k1c8bit.pcm"</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//设置默认IP和端口</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">lineEditIP</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setText</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">"127.0.0.1"</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">lineEditPort</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setText</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">"12345"</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//限定端口号范围</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QIntValidator</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span><span style=" color:#000000;">vali</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#808000;">new</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QIntValidator</span><span
style=" color:#000000;">(</span><span style=" color:#000080;">1</span><span style=" color:#000000;">,</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">65535</span><span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">lineEditPort</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setValidator</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">vali</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre></div>
          
          该函数调用 QAudioDeviceInfo 类静态函数，获取所有音频输入设备列表，保存到成员变量 m_listDevices；<br>然后将所有音频输入设备的设备名称添加为 comboBoxDeviceIn 组合框的条目。<br>由于组合框原本没有条目，因此组合框在添加条目时，从无到有的过程会自动触发 currentIndexChanged( 0 ) 信号，参数是默认的序号 0，这个信号对应的槽函数稍后讲解。<br><br>设置组合框之后，我们设置默认的文件名为&nbsp; "E:/audio_8k1c8bit.pcm" ，Qt 的文件路径通常都是右斜杠分隔，遵循 Unix/Linux 的路径习惯。因为 pcm 文件是非常裸的数据格式，没有文件头表示音频的采样参数，<b>因此本教程约定用文件名标出关键参数：<br>以 audio_8k1c8bit.pcm 为例，audio 是自定义的名字，然后接下划线，下划线后面：<br>8k 代表 8000 采样频率，如果是 CD 倍率，11k 代表 11025，以此类推；<br>1c 代表 1 个通道，单声道采样；<br>8bit 代表采样位宽是 8 比特；<br>对于 8bit 位宽，我们约定采用无符号整数类型采样；对于 16bit 位宽，我们约定用有符号整数类型采样。<br>编码格式都是 "audio/pcm" ，字节序就用默认的主机字节序，绝大部分情况下是小端字节序。</b><br><br>设置默认文件名之后，然后设置默认的目标IP 为本地环路地址，端口为 12345；<br>并且新建整数验证器，限定整数范围 1 ~ 65535，把整数验证器设置给端口单行编辑器。<br><br>设备组合框 comboBoxDeviceIn 的条目序号变化时，自动调用如下槽函数：<br>
    <div class="code">
<style type="text/css">
p, li { white-space: pre-wrap; }
</style>

<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#008000;">//设备名变化时，自动更新设备支持的采样参数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">void</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">WidgetAudioIn</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">on_comboBoxDeviceIn_currentIndexChanged</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">index</span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">if</span><span
style=" color:#000000;">(</span><span style=" color:#000000;">index</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">&lt;</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">0</span><span style=" color:#000000;">)</span><span style=" color:#c0c0c0;">   </span><span
style=" color:#808000;">return</span><span style=" color:#000000;">;</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//序号不合法，不处理</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//序号合法</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//根据设备添加支持的采样频率</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QList</span><span
style=" color:#000000;">&lt;</span><span style=" color:#808000;">int</span><span
style=" color:#000000;">&gt;</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">listSampleRates</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800000;">m_listDevices</span><span style=" color:#000000;">[</span><span
style=" color:#000000;">index</span><span style=" color:#000000;">].</span><span
style=" color:#000000;">supportedSampleRates</span><span style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//清空旧的采样频率列表</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxSampleRate</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">clear</span><span
style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//添加新的</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">for</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">i</span><span style=" color:#000000;">=</span><span style=" color:#000080;">0</span><span
style=" color:#000000;">;</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">i</span><span
style=" color:#000000;">&lt;</span><span style=" color:#000000;">listSampleRates</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">count</span><span
style=" color:#000000;">();</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">i</span><span
style=" color:#000000;">++)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxSampleRate</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">addItem</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tr</span><span
style=" color:#000000;">(</span><span style=" color:#008000;">"%1"</span><span style=" color:#000000;">).</span><span
style=" color:#000000;">arg</span><span style=" color:#000000;">(</span><span style=" color:#000000;">listSampleRates</span><span
style=" color:#000000;">[</span><span style=" color:#000000;">i</span><span style=" color:#000000;">])</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//通道数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QList</span><span
style=" color:#000000;">&lt;</span><span style=" color:#808000;">int</span><span
style=" color:#000000;">&gt;</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">listChannels</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800000;">m_listDevices</span><span style=" color:#000000;">[</span><span
style=" color:#000000;">index</span><span style=" color:#000000;">].</span><span
style=" color:#000000;">supportedChannelCounts</span><span style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//清空旧的通道数列表</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxChannelCount</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">clear</span><span
style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//添加新的</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">for</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">i</span><span style=" color:#000000;">=</span><span style=" color:#000080;">0</span><span
style=" color:#000000;">;</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">i</span><span
style=" color:#000000;">&lt;</span><span style=" color:#000000;">listChannels</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">count</span><span
style=" color:#000000;">();</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">i</span><span
style=" color:#000000;">++)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxChannelCount</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">addItem</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tr</span><span
style=" color:#000000;">(</span><span style=" color:#008000;">"%1"</span><span style=" color:#000000;">).</span><span
style=" color:#000000;">arg</span><span style=" color:#000000;">(</span><span style=" color:#000000;">listChannels</span><span
style=" color:#000000;">[</span><span style=" color:#000000;">i</span><span style=" color:#000000;">])</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//采样位宽</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QList</span><span
style=" color:#000000;">&lt;</span><span style=" color:#808000;">int</span><span
style=" color:#000000;">&gt;</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">listSizes</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800000;">m_listDevices</span><span style=" color:#000000;">[</span><span
style=" color:#000000;">index</span><span style=" color:#000000;">].</span><span
style=" color:#000000;">supportedSampleSizes</span><span style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//清空旧的位宽列表</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxSampleSize</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">clear</span><span
style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//添加新的</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">for</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">i</span><span style=" color:#000000;">=</span><span style=" color:#000080;">0</span><span
style=" color:#000000;">;</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">i</span><span
style=" color:#000000;">&lt;</span><span style=" color:#000000;">listSizes</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">count</span><span
style=" color:#000000;">();</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">i</span><span
style=" color:#000000;">++)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxSampleSize</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">addItem</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tr</span><span
style=" color:#000000;">(</span><span style=" color:#008000;">"%1"</span><span style=" color:#000000;">).</span><span
style=" color:#000000;">arg</span><span style=" color:#000000;">(</span><span style=" color:#000000;">listSizes</span><span
style=" color:#000000;">[</span><span style=" color:#000000;">i</span><span style=" color:#000000;">])</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//采样点数据类型</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QList</span><span
style=" color:#000000;">&lt;</span><span style=" color:#800080;">QAudioFormat</span><span
style=" color:#000000;">::</span><span style=" color:#800080;">SampleType</span><span
style=" color:#000000;">&gt;</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">listTypes</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800000;">m_listDevices</span><span style=" color:#000000;">[</span><span
style=" color:#000000;">index</span><span style=" color:#000000;">].</span><span
style=" color:#000000;">supportedSampleTypes</span><span style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//清空旧的类型列表</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxSampleType</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">clear</span><span
style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//添加新的</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">for</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">i</span><span style=" color:#000000;">=</span><span style=" color:#000080;">0</span><span
style=" color:#000000;">;</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">i</span><span
style=" color:#000000;">&lt;</span><span style=" color:#000000;">listTypes</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">count</span><span
style=" color:#000000;">();</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">i</span><span
style=" color:#000000;">++)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800080;">QString</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strType</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800000;">m_listSampleTypes</span><span style=" color:#000000;">[</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">listTypes</span><span
style=" color:#000000;">[</span><span style=" color:#000000;">i</span><span style=" color:#000000;">]</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">];</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#008000;">//第一个参数是显示字符串，第二个参数是条目关联的用户数据，保存采样类型数值</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxSampleType</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">addItem</span><span
style=" color:#000000;">(</span><span style=" color:#000000;">strType</span><span
style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">listTypes</span><span
style=" color:#000000;">[</span><span style=" color:#000000;">i</span><span style=" color:#000000;">]</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//如果默认位宽是</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">8，设置默认用无符号整数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">if</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000080;">8</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">==</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">listSizes</span><span style=" color:#000000;">[</span><span
style=" color:#000080;">0</span><span style=" color:#000000;">]</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#008000;">//无符号整数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxSampleType</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setCurrentText</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_listSampleTypes</span><span
style=" color:#000000;">[</span><span style=" color:#000080;">2</span><span style=" color:#000000;">]</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">else</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#008000;">//其他情况默认用有符号整数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxSampleType</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setCurrentText</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_listSampleTypes</span><span
style=" color:#000000;">[</span><span style=" color:#000080;">1</span><span style=" color:#000000;">]</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre></div>
          
          
          
          
          该函数的参数 index 是组合框选择的条目变化之后的新条目序号，要注意这个参数有可能是 -1，<br>组合框被清空或者调用析构函数会触发参数为 -1 的序号变化信号，所以一定要判断参数 index，如果为 -1，那么不处理，直接返回。<br>新序号 index 合法时，进行后面操作：<br>我们获取 index 序号的音频采集设备支持的采样频率列表 listSampleRates ；<br>清空采样频率的组合框 comboBoxSampleRate；<br>将采样频率列表的数值转为文本，逐一添加给组合框 comboBoxSampleRate。<br>后面通道数组合框 comboBoxChannelCount、采样位宽组合框 comboBoxSampleSize、采样点数据类型组合框 comboBoxSampleType 的更新代码是完全类似的。<br>稍微有区别的是采样类型 comboBoxSampleType 的代码，因为 Qt 定义的类型数值是从 0 到 3，如果显示数字用户会看不懂，所以我们提前准备了字符串列表 m_listSampleTypes，将采样类型对应的字符串显示到组合框，并把类型数值设置为条目的用户数据，方便后面提取类型的数值。<br>该函数末尾，我们判断默认的采样位宽，如果是 8 bit，那么选择采样类型为无符号整数 "UnSignedInt"，其他位宽都是用有符号整数 "SignedInt" 。<br>该槽函数会被  InitFindDevices() 函数触发一次，显示序号 0 的音频采样设备支持的参数；<br>如果系统有多个音频采集设备，用户选择其他采集设备时，也会触发该槽函数，更新指定设备支持的采样参数。<br><br>下面我们编辑“开始”按钮的槽函数代码：<br>
  <div class="code">
<style type="text/css">
p, li { white-space: pre-wrap; }
</style>

<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#008000;">//开始录音和UDP发送</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">void</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">WidgetAudioIn</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">on_pushButtonStart_clicked</span><span
style=" color:#000000;">()</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//如果没有声卡不处理</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">if</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_listDevices</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">count</span><span
style=" color:#000000;">()</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">&lt;</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">1</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">return</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//先尝试打开文件</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_fileSave</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">setFileName</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">lineEditFile</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">text</span><span
style=" color:#000000;">()</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">if</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">!</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_fileSave</span><span
style=" color:#000000;">.</span><span style=" font-style:italic; color:#000000;">open</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QIODevice</span><span
style=" color:#000000;">::</span><span style=" color:#800080;">WriteOnly</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">)</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#008000;">//无法打开</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800080;">QMessageBox</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">warning</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">this</span><span style=" color:#000000;">,</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span
style=" color:#008000;">"打开文件"</span><span style=" color:#000000;">),</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span
style=" color:#008000;">"无法打开指定文件名，不能开始录音。"</span><span style=" color:#000000;">));</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">return</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//获取IP和端口</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QString</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strIP</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800000;">ui</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#800000;">lineEditIP</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#000000;">text</span><span style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nPort</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800000;">ui</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#800000;">lineEditPort</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#000000;">text</span><span style=" color:#000000;">().</span><span
style=" color:#000000;">toUShort</span><span style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QHostAddress</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">dstHost</span><span
style=" color:#000000;">;</span><span style=" color:#008000;">//网络地址对象</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">bool</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">bRet</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">dstHost</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">setAddress</span><span
style=" color:#000000;">(</span><span style=" color:#000000;">strIP</span><span
style=" color:#000000;">);</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//尝试把字符串转为IP地址格式</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">if</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">!</span><span
style=" color:#000000;">bRet</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#008000;">//转换失败</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800080;">QMessageBox</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">warning</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">this</span><span style=" color:#000000;">,</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span
style=" color:#008000;">"IP设置"</span><span style=" color:#000000;">),</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span
style=" color:#008000;">"IP地址不合法，请重新设置IP。"</span><span style=" color:#000000;">));</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">m_fileSave</span><span
style=" color:#000000;">.</span><span style=" font-style:italic; color:#000000;">close</span><span
style=" color:#000000;">();</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//关闭之前打开的文件</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">return</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//新建网络套接字</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_pSocket</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#808000;">new</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QUdpSocket</span><span
style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//建立连接，UDP的连接函数仅用于设置目标IP和端口</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_pSocket</span><span
style=" color:#000000;">-&gt;</span><span style=" font-style:italic; color:#000000;">connectToHost</span><span
style=" color:#000000;">(</span><span style=" color:#000000;">dstHost</span><span
style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nPort</span><span
style=" color:#000000;">);</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//文件和网络的准备工作就绪</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//选择的声卡</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QAudioDeviceInfo</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">dev</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_listDevices</span><span
style=" color:#000000;">[</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxDeviceIn</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">currentIndex</span><span
style=" color:#000000;">()</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">];</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//设置音频采样格式</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//采样频率</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_aFormat</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">setSampleRate</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxSampleRate</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">currentText</span><span
style=" color:#000000;">().</span><span style=" color:#000000;">toInt</span><span
style=" color:#000000;">()</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//通道数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_aFormat</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">setChannelCount</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxChannelCount</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">currentText</span><span
style=" color:#000000;">().</span><span style=" color:#000000;">toInt</span><span
style=" color:#000000;">()</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//采样位宽</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_aFormat</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">setSampleSize</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxSampleSize</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">currentText</span><span
style=" color:#000000;">().</span><span style=" color:#000000;">toInt</span><span
style=" color:#000000;">()</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//采样点数据类型</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QAudioFormat</span><span
style=" color:#000000;">::</span><span style=" color:#800080;">SampleType</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">curType</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">            </span><span style=" color:#000000;">(</span><span
style=" color:#800080;">QAudioFormat</span><span style=" color:#000000;">::</span><span
style=" color:#800080;">SampleType</span><span style=" color:#000000;">)(</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">ui</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#800000;">comboBoxSampleType</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#000000;">currentData</span><span style=" color:#000000;">().</span><span
style=" color:#000000;">toInt</span><span style=" color:#000000;">()</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_aFormat</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">setSampleType</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">curType</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//字节序不用设置，用系统默认值</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//编码格式固定用PCM</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_aFormat</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">setCodec</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">"audio/pcm"</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//判断格式是否支持</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">if</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">!</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">dev</span><span style=" color:#000000;">.</span><span
style=" color:#000000;">isFormatSupported</span><span style=" color:#000000;">(</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_aFormat</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">)</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()&lt;&lt;</span><span style=" color:#008000;">"old</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">audioFomat</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">is</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">not</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">supported:</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">"</span><span style=" color:#000000;">&lt;&lt;</span>endl<span
style=" color:#000000;">&lt;&lt;</span><span style=" color:#800000;">m_aFormat</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#008000;">//获取近似支持的格式</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">m_aFormat</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">dev</span><span style=" color:#000000;">.</span><span style=" color:#000000;">nearestFormat</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_aFormat</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()&lt;&lt;</span><span style=" color:#008000;">"used</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">Format:</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">"</span><span style=" color:#000000;">&lt;&lt;</span>endl<span
style=" color:#000000;">&lt;&lt;</span><span style=" color:#800000;">m_aFormat</span><span
style=" color:#000000;">&lt;&lt;</span>endl<span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//新建</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_pInput</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#808000;">new</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QAudioInput</span><span
style=" color:#000000;">(</span><span style=" color:#000000;">dev</span><span style=" color:#000000;">,</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_aFormat</span><span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//关联状态变化的信号到槽函数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">connect</span><span
style=" color:#000000;">(</span><span style=" color:#800000;">m_pInput</span><span
style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">SIGNAL</span><span
style=" color:#000000;">(</span>stateChanged<span style=" color:#000000;">(</span><span
style=" color:#800080;">QAudio</span><span style=" color:#000000;">::</span><span
style=" color:#800080;">State</span><span style=" color:#000000;">)),</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">            </span><span style=" color:#808000;">this</span><span
style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">SLOT</span><span
style=" color:#000000;">(</span>onDeviceStateChanged<span style=" color:#000000;">(</span><span
style=" color:#800080;">QAudio</span><span style=" color:#000000;">::</span><span
style=" color:#800080;">State</span><span style=" color:#000000;">))</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//开始采集</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_pBuffDevice</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800000;">m_pInput</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#000000;">start</span><span style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//关联缓冲区数据可读信号到槽函数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">connect</span><span
style=" color:#000000;">(</span><span style=" color:#800000;">m_pBuffDevice</span><span
style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">SIGNAL</span><span
style=" color:#000000;">(</span>readyRead<span style=" color:#000000;">()),</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">            </span><span style=" color:#808000;">this</span><span
style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">SLOT</span><span
style=" color:#000000;">(</span>onBuffReadyRead<span style=" color:#000000;">())</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//开始采样后，禁止修改采样参数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">holdParas</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">true</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre></div>          
          
          
          该函数首先判断音频采集设备的数量，如果没有采集声卡设备，那么直接返回。<br>存在音频采集设备时，将文件名设置给 m_fileSave 对象，并尝试以只写模式打开指定文件名；<br>如果打开失败，就提示无法打开并返回；<br>如果打开成功继续后面代码：<br>获取目标 IP 的字符串和端口号数值，因为我们对端口号采用了整数验证器，所以不需要判断端口号，能够输入的端口号总是在 1 ~ 65535 范围内；<br>对于 IP 地址，我们定义地址对象 dstHost，尝试把地址的字符串设置给该对象；<br>如果地址字符串不合法，那么提示消息框说明地址不合法，关闭之前打开的文件，然后返回；<br>如果地址字符串合法，那么我们得到可用的地址对象 dstHost；<br>我们新建 UDP 套接字对象，保存到指针 m_pSocket，然后调用连接主机函数，连接到 dstHost 主机、端口号 nPort。<br>UDP 套接字是无连接的，这里的连接函数仅仅用于指定目标地址和端口号，并不会真的有连接，指定目标地址和端口号之后，以后我们发送数据就不需要重复填写地址和端口号参数了。<br><br>文件和网络套接字准备完毕后，我们获取用户选择的音频采集设备 dev ；<br>然后将组合框里选择的采样参数填充到 m_aFormat 音频采样格式对象，包括采样频率、采样通道数、采样位宽、采样点数据类型，采样点数据类型的设置稍有不同，我们先获取选中条目的用户数据，强制类型转换为 QAudioFormat::SampleType 类型的 curType，将这个数值设置给音频采样格式对象。<br>采样格式的字节序不需要设置，音频编码固定设置为 "audio/pcm" 。<br><br>设置 m_aFormat 之后，我们检查一下音频输入设备是否支持  m_aFormat；<br>如果不支持就获取与  m_aFormat 最接近的采样格式，进行后续的音频采样。<br>然后打印实际使用的采样格式信息到调试输出窗口。<br><br>然后我们根据选定的设备和采样格式，新建音频输入对象，保存到指针 m_pInput，我们关联该对象的状态变化信号到槽函数 onDeviceStateChanged(QAudio::State)，实时监控采集时的状态变化；<br>然后我们开始采集，调用 m_pInput-&gt;start()，将返回的内存缓冲区设备指针存到 m_pBuffDevice；<br>我们关联内存缓冲区设备的数据准备好的信号到槽函数 onBuffReadyRead()，这样就能实时读取音频采样数据。<br>最后调用的 holdParas(true) ，保证我们在进行音频采集时，将各个输入控件禁用，用户不能修改采样参数，在采集停止之后再恢复各个控件。<br>&nbsp;<br>禁用或启用输入控件的函数如下：<br>
 <div class="code">
<style type="text/css">
p, li { white-space: pre-wrap; }
</style>

<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#008000;">//开始采样时，禁止修改采样参数，停止后恢复</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">void</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">WidgetAudioIn</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">holdParas</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">bool</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">bHold</span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">if</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">bHold</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#008000;">//组合框和编辑框全部禁用</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxDeviceIn</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setEnabled</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">false</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxSampleRate</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setEnabled</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">false</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxChannelCount</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setEnabled</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">false</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxSampleSize</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setEnabled</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">false</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxSampleType</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setEnabled</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">false</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">lineEditFile</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setEnabled</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">false</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">lineEditIP</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setEnabled</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">false</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">lineEditPort</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setEnabled</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">false</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#008000;">//开始按钮也禁用</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">pushButtonStart</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setEnabled</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">false</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">else</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#008000;">//组合框和编辑框全部启用</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxDeviceIn</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setEnabled</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">true</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxSampleRate</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setEnabled</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">true</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxChannelCount</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setEnabled</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">true</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxSampleSize</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setEnabled</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">true</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxSampleType</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setEnabled</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">true</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">lineEditFile</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setEnabled</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">true</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">lineEditIP</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setEnabled</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">true</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">lineEditPort</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setEnabled</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">true</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#008000;">//开始按钮也启用</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">pushButtonStart</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setEnabled</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">true</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre></div>  
          
          当参数 bHold 为 true 时，我们禁用 5 个组合框、3 个单行编辑器和“开始”按钮，保证音频采集时用户不能修改这些采样参数；<br>当参数 bHold 为 false 时，我们重新启用这些组合框、单行编辑器和“开始”按钮，这样用户就能重新设置采样参数，开始新的采集过程。<br><br>当音频采集对象的工作状态发生变化时，会自动触发下面的槽函数：<br>
  <div class="code">
<style type="text/css">
p, li { white-space: pre-wrap; }
</style>

<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">void</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">WidgetAudioIn</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">onDeviceStateChanged</span><span
style=" color:#000000;">(</span><span style=" color:#800080;">QAudio</span><span
style=" color:#000000;">::</span><span style=" color:#800080;">State</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">state</span><span
style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//打印状态变化</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()&lt;&lt;</span><span style=" color:#000000;">state</span><span
style=" color:#000000;">&lt;&lt;</span>endl<span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">if</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QAudio</span><span
style=" color:#000000;">::</span><span style=" color:#800080;">NoError</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">!=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800000;">m_pInput</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#000000;">error</span><span style=" color:#000000;">()</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#008000;">//打印错误编号</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()&lt;&lt;</span><span style=" color:#008000;">"Error:</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">"</span><span style=" color:#000000;">&lt;&lt;</span><span
style=" color:#800000;">m_pInput</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#000000;">error</span><span style=" color:#000000;">()&lt;&lt;</span>endl<span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre></div>
          
          该函数直接打印当前的状态，然后判断音频输入对象是否出错，如果出错了，将出错的信息打印出来。<br><br>接下来是非常重要的实时读取音频采集数据函数，代码特别简单：<br>
  <div class="code">
<style type="text/css">
p, li { white-space: pre-wrap; }
</style>

<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">void</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">WidgetAudioIn</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">onBuffReadyRead</span><span
style=" color:#000000;">()</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000080;">qDebug</span><span
style=" color:#000000;">()&lt;&lt;</span><span style=" color:#008000;">"Bytes</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">ready:</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">"</span><span style=" color:#000000;">&lt;&lt;</span><span
style=" color:#800000;">m_pInput</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#000000;">bytesReady</span><span style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//读取缓冲区</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QByteArray</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">baData</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800000;">m_pBuffDevice</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#000000;">readAll</span><span style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//写入文件</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_fileSave</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">write</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">baData</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//发送网络</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_pSocket</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">write</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">baData</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre></div>
          
          当内存缓冲区设备准备好采集的音频数据后，会自动调用上面的槽函数，源源不断地采集数据，就会源源不断地调用该槽函数。<br>该函数先打印采集的数据字节数，调用 m_pInput-&gt;bytesReady() 可以获知实时采样得到的字节数；<br>然后我们从内存缓冲区设备读取目前采到的全部音频数据，存到 baData ；<br>Qt 的文件类和网络套接字的基类都是 QIODevice，读写函数都一样，写入文件或发送到网络都是 write() 函数，从文件读取或从套接字接收，都是 read() 或 readAll()。<br>我们将 baData 写入到文件，然后从套接字发送出去。实时采集、录音、网络发送的功能就完成了。<br><br>最后我们编辑“停止”按钮的槽函数代码：<br>
<div class="code">
<style type="text/css">
p, li { white-space: pre-wrap; }
</style>

<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#008000;">//停止</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">void</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">WidgetAudioIn</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">on_pushButtonStop_clicked</span><span
style=" color:#000000;">()</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">if</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000080;">NULL</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">==</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800000;">m_pInput</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#008000;">//没有开始，直接返回</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">return</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//停止录音</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_pInput</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">stop</span><span
style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//删除录音对象</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">delete</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_pInput</span><span
style=" color:#000000;">;</span><span style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_pInput</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">NULL</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//停止网络</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_pSocket</span><span
style=" color:#000000;">-&gt;</span><span style=" font-style:italic; color:#000000;">disconnectFromHost</span><span
style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//删除套接字</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">delete</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_pSocket</span><span
style=" color:#000000;">;</span><span style=" color:#c0c0c0;">   </span><span style=" color:#800000;">m_pSocket</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">NULL</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//关闭文件</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_fileSave</span><span
style=" color:#000000;">.</span><span style=" font-style:italic; color:#000000;">close</span><span
style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//缓冲区设备对象归录音对象管理，不要手动删除，把指针设置为</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">NULL</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">即可</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_pBuffDevice</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">NULL</span><span style=" color:#000000;">;</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//恢复组合框、编辑框、开始按钮</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">holdParas</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">false</span><span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre></div>
          
          我们先判断音频采集对象的指针 m_pInput 是否为空，如果为空说明没开始录音，不处理直接返回。<br>如果  m_pInput 不为空，进行后面操作：<br>停止音频采集，删除音频采集对象，将 m_pInput 指针置空；<br>停止网络套接字，删除套接字对象，将 m_pSocket 指针置空；<br>关闭录音文件；<br>将指针 m_pBuffDevice 直接置空，因为内存缓冲区设备归采集对象管理，不能手动删除该设备对象。<br>函数最后调用 holdParas(false)，恢复组合框、单行编辑器和“开始”按钮为可用状态。<br><br>代码讲解完了，由于示例涉及到网络发送，我们先运行之前下载的网络调试助手 NetAssist.exe，看到如下界面：<br>
           <center> <img src="images/ch03/ch03-01-05.png" alt="run"> </center>

          左上角协议类型选择“UDP”，本地主机地址选择“0.0.0.0”，本地主机端口设置为 12345，<br>然后点击“打开”按钮，在本机监听 UDP 12345 端口：<br>
           <center> <img src="images/ch03/ch03-01-06.png" alt="run"> </center>
          
          如果有数据发送到本机的 UDP 12345 端口，网络调试助手会自动把接收的数据显示到右边的接收框里面。<br><br><b>我们将麦克风或带麦克风的耳机连接到电脑音频接口，</b>然后构建并运行示例程序，看到示例的界面：<br>
            <center> <img src="images/ch03/ch03-01-07.png" alt="run"> </center>
          示例程序启动时自动显示了第一个音频采集设备，及其支持的采样参数，还有默认的文件路径，目标 IP 、端口号。<br><br>我们点击“开始”按钮，然后可以在网络调试助手收到发送的网络数据：<br>
            <center> <img src="images/ch03/ch03-01-08.png" alt="run" width="800"> </center>
          开始录音和网络发送之后，网络调试助手显示收到了发送的数据，并且在 E: 盘有录音文件 audio_8k1c8bit.pcm 。<br>我们点击“停止”按钮，就可以停止录音和网络发送。<br>QtCreator 的应用程序输出窗口可以看到实时采集的字节数，如果停止采集，可以看到状态变为 StoppedState 。<br><br>读者可以选择其他采样参数进行音频采集，但要注意修改保存的文件名，按照类似 audio_8k1c8bit.pcm 的命名，标出采样频率、通道数和位宽，8bit位宽使用无符号整数类型，其他位宽使用有符号整数类型。本节的内容介绍到这，我们下一节学习如何播放原始 PCM 数据流。<br><br>
    <br>
    <br>
    <table style="text-align: left; width: 100%;" border="0" cellpadding="2" cellspacing="2">
      <tbody>
        <tr>
          <td style="width: 40%;">
            <div style="text-align: center;"><a href="ch03-00.htm"><img class="pic"
style="width: 32px; height: 32px;" alt="prev" src="images/pics/prev.png"></a></div>
          </td>
          <td style="width: 20%;">
            <div style="text-align: center;"><a href="contents.htm"><img class="pic"
style="width: 32px; height: 32px;" alt="contents" src="images/pics/contents.png"></a></div>
          </td>
          <td style="width: 40%;">
            <div style="text-align: center;"><a href="ch03-02.htm"><img class="pic"
style="width: 32px; height: 32px;" alt="next" src="images/pics/next.png"></a></div>
          </td>
        </tr>
      </tbody>
    </table>
</body></html>